﻿<html>
<head>
<script type="text/javascript" src="raphael.js"></script>
<script type="text/javascript">

    function jieObj(nodesArray, coordOnMap, nodesRaphObj, linksRaphObj) {
        
        this.nodesArray = nodesArray;
        this.coordOnMap = coordOnMap;
        this.nodesRaphObj = nodesRaphObj;
        this.linksRaphObj = linksRaphObj;
    }

    function nodeObj(urlArray, bubbRaphObj) {

        this.urlArray = urlArray;
        this.bubbRaphObj = bubbRaphObj;
    }
    
    function Matrix(nr, nc, init) {
        
        this.data = new Array(nr);

        for (i = 0; i < nr; i++) {
            
            this.data[i] = new Array(nc);

            for (j = 0; j < nc; j++) {
                this.data[i][j] = init;
            }
        }
    }

    function SearchFreeAdjacent(currCoord, dirPrior) {
        
        var k = 0;
        var dirFound = -1;
        var currRow = currCoord[0];
        var currCol = currCoord[1];
        
        while ((dirFound == -1) && (k < 8)) {
            switch (dirPrior[k]) {
                // Right
                case 1:
                    newRowCand = currRow;
                    newColCand = currCol + 1;
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;

                // Diag Down rigth   
                case 2:
                    newRowCand = currRow + 1;
                    newColCand = currCol + 1;
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;

                // Down   
                case 3:
                    newRowCand = currRow + 1;
                    newColCand = currCol;
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;
                    
                // Diag Down left
                case 4:
                    newRowCand = currRow + 1;
                    newColCand = currCol - 1;
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;

                // Left   
                case 5:
                    newRowCand = currRow;
                    newColCand = currCol - 1;
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;

                // Diag Up left 
                case 6:
                    newRowCand = currRow - 1;
                    newColCand = currCol - 1;
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;

                // Up  
                case 7:
                    newRowCand = currRow - 1;
                    newColCand = currCol;
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;

                // Diag Up right
                case 8:
                    newRowCand = currRow - 1;
                    newColCand = currCol + 1;
                    
                    if (((newRowCand >= 0) && (newRowCand < NrowsMap) && (newColCand >= 0) && (newColCand < NcolsMap)) && (jieMapUse.data[newRowCand][newColCand] < nNmax)) {
                        newRow = newRowCand;
                        newCol = newColCand;
                        dirFound = dirPrior[k];
                    }
                    break;
            }
            k++;
        }
        
        var retObj = new Object();

        retObj.dirFound = dirFound;
        retObj.newCoord = [newRow, newCol];
                
        return retObj;
    }

    function FindEmptyCoordinates(nNodes, initCoord, dirPrior) {
        var coordList = new Array();
        var placedNodes = 0;
        var initNode = 0;
        var success = 1;

        currCoord = initCoord;

        if (jieMapUse.data[initCoord[0]][initCoord[1]] < nNmax) {
            coordList[0] = currCoord;
            jieMapUse.data[currCoord[0]][currCoord[1]]++;
            initNode = 1;   
        }

        for (i = initNode; i < nNodes; i++) {
            retObj = SearchFreeAdjacent(currCoord, dirPrior);

            if (retObj.dirFound >= 0) {
                coordList.push(retObj.newCoord);
                jieMapUse.data[retObj.newCoord[0]][retObj.newCoord[1]]++;
            }
            else {
                success = -1;
                break;
            }
        }

        var retObj = new Object();

        retObj.freeCoord = coordList;
        retObj.success = success;

        return retObj;
    }
    
    function AddMouseEvents(jie) {
        var nNodes = jie.nodesArray.length;
        for (i = 0; i < nNodes; i++) {
            nBubbs = jie.nodesArray[i].urlArray.length;
            for (j = 0; j < nBubbs; j++) {
                currBubb = jie.nodesArray[i].bubbRaphObj[j];
                currBubb.node.onclick = function () {
                    
                }
            }
        }
    }
    
    function AddJieToMap(jie, initCoord, dirPrior) {
        retObj = FindEmptyCoordinates(jie.nodesArray.length, initCoord,dirPrior);

        if (retObj.success == 1) {
            jie.coordOnMap = retObj.freeCoord;
        }
        
        DrawJie(jie);
        //AddMouseEvents(jie);

        return retObj.success;
    }

    function Distance(x0Cood,x1Cood) {
        var deltax  = (x0Cood[1]-x1Cood[1]);
        var deltay  = (x0Cood[0]-x1Cood[0]);
            
        return Math.sqrt(deltax*deltax + deltay*deltay);
    }

    function Angle(x0Cood, x1Cood) {
        var deltax = (x1Cood[1] - x0Cood[1]);
        var deltay = (x1Cood[0] - x0Cood[0]);

        return Math.atan2(deltay,deltax);
    }

    function Rad2Deg(x) {
        return x*180/Math.PI;   
    }

    function Deg2Rad(x) {
        return x*Math.PI/180;   
    }

    function DrawBubbs(jie) {
        var nNodes = jie.nodesArray.length;
        var thBubb = new Array();
        var arrayBubbs = new Array();
        var arrayLinks = new Array();    

        for (i = 0; i < nNodes; i++) {
            nBubbs = jie.nodesArray[i].urlArray.length;
            relCoordBubbs = new Array(nBubbs);

            if (jieMapUse.data[jie.coordOnMap[i][0]][jie.coordOnMap[i][1]] == 1) {

                if (nBubbs == 1) {
                    relCoordBubbs[0] = [0, 0];
                }
                else {
                    for (j = 0; j < nBubbs; j++) {
                        thBubb[j] = j * 2 * Math.PI / nBubbs + th0Bubb;
                        relCoordBubbs[j] = [bubbDist * Math.cos(thBubb[j]), bubbDist * Math.sin(thBubb[j])];
                    }
                }

                for (j = 0; j < nBubbs; j++) {
                    nodeCenter = [jie.coordOnMap[i][1] * grid2pix + margin, jie.coordOnMap[i][0] * grid2pix + margin]
                    bubbCen = [nodeCenter[0] + relCoordBubbs[j][0], nodeCenter[1] + relCoordBubbs[j][1]];

                    if (nBubbs > 1) {
                        var blink = paper.rect(nodeCenter[0], nodeCenter[1] - thckBubbLink / 2, bubbDist, thckBubbLink);
                        blink.hide();
                        arrayLinks.push(blink);

                        blink.rotate(Rad2Deg(thBubb[j]),nodeCenter[0], nodeCenter[1]);

                        blink.attr("fill", bubbLinkColor);
                        blink.attr("stroke-width", 0);
                        blink.show();
                    }
                    
                    var circle = paper.circle(bubbCen[0], bubbCen[1], radiusBubb);
                    circle.attr("fill", bubbColor);
                    circle.attr("stroke", bubbLineColor);
                    circle.attr("stroke-width", bubbLineThk);

                    arrayBubbs.push(circle);
                }

                jie.nodesArray[i].bubbRaphObj = arrayBubbs;
            }
        }
        
    }

    function DrawJie(jie) {
        var nNodes = jie.nodesArray.length;
        var arrayNodes = new Array();
        var arrayLinks = new Array();
        var arrayAngLinks = new Array();
        
        for (i = 0; i < nNodes - 1; i++) {
            var x0Cood = jie.coordOnMap[i];
            var x1Cood = jie.coordOnMap[i+1];

            var lghLink = Distance(x0Cood,x1Cood);
            var clink = paper.rect((x0Cood[1] * grid2pix) + margin, (x0Cood[0] * grid2pix) + margin - thckLink / 2, lghLink * grid2pix, thckLink);
            clink.hide();

            arrayLinks.push(clink);

            var angLink = Angle(x0Cood, x1Cood);

            arrayAngLinks.push(angLink);

            clink.rotate(Rad2Deg(angLink), (x0Cood[1] * grid2pix) + margin, (x0Cood[0] * grid2pix) + margin);

            clink.attr("fill", linkColor);
            clink.attr("stroke", linkLineColor);
            clink.attr("stroke-width", linkThk);

            clink.show();
        }

        jie.angLinksRaph = arrayAngLinks;
        jie.linksRaphObj = arrayLinks;

        for (i = 0; i < nNodes; i++) {
            var x0Cood = jie.coordOnMap[i];
            var circle = paper.circle(x0Cood[1] * grid2pix + margin, x0Cood[0] * grid2pix + margin, radius);

            arrayNodes.push(circle);

            circle.attr("fill",nodeColor);
            circle.attr("stroke", nodeLineColor);
            circle.attr("stroke-width",nodeLineThk);
        }

        jie.nodesRaphObj = arrayNodes;

        DrawBubbs(jie);
        
    }

</script>
</head>

<body>
    <p id="fstRow">First row text </p>
    <div id="canvas_container"></div> 

    <script type="text/javascript">
        var NrowsMap = 10;
        var NcolsMap = 10;
        var nNmax = 1;
        var grid2pix = 70;
        var margin = 50;

        var xSize = NcolsMap * grid2pix + 2 * margin;
        var ySize = NrowsMap * grid2pix + 2 * margin;

        var radius = 5;                 
        var nodeLineThk = 0;
        var nodeColor = "9EA0AE";      
        var nodeLineColor = "81BCC0";  

        var thckLink = 4;               
        var linkThk = 0;
        var linkColor = "9EA0AE";
        var linkLineColor = "9EA0AE";

        var bubbDist = 15;
        var th0Bubb = Deg2Rad(-90);
        var radiusBubb = 5;             
        var bubbLineThk = 1;
        var bubbColor = "D0FA58";
        var bubbLineColor = "4B610B";

        var thckBubbLink = 2;
        var bubbLinkColor = "9EA0AE";
                
        var paper = new Raphael(document.getElementById('canvas_container'), xSize,ySize );
        
        for (i = 0; i < NcolsMap; i++) {
            for (j = 0; j < NrowsMap; j++) {
                var dummy = paper.rect(i * grid2pix + margin - grid2pix / 2, j * grid2pix + margin - grid2pix / 2, grid2pix, grid2pix);
                dummy.attr("stroke", "#E9E9E9");
            } 
        }
        
        var url001 = "xttp://www.webjies.com/";
        var url002 = "xttp://www.webjies.com/";
        var url003 = "xttp://www.webjies.com/";
        var url004 = "xttp://www.webjies.com/";
        var url005 = "xttp://www.webjies.com/";
        var url006 = "xttp://www.webjies.com/";
    
        var node001 = new nodeObj([url001],[]);
        var node002 = new nodeObj([url002, url002, url002, url002, url002, url002], []);
        var node003 = new nodeObj([url003], []);
        var node004 = new nodeObj([url004, url004, url004], []);
        var node005 = new nodeObj([url005, url005], []);

        var jie001 = new jieObj([node001, node002, node003], 0, [], []);
        var jie002 = new jieObj([node004, node005], 0, [], []);
        var jie003 = new jieObj([node001, node002, node003, node001, node002, node003], 0, [], []);
        var jie004 = new jieObj([node004, node005, node001, node002, node003], 0, [], []);
        var jie005 = new jieObj([node004, node005, node003], 0, [], []);

        var jieMapUse = new Matrix(NrowsMap, NcolsMap, 0);

        var initCoord = [0,0];
        var dirPrior = [3, 8, 2, 4, 5, 6, 7, 1];
        AddJieToMap(jie001, initCoord, dirPrior);

        var initCoord = [0, 0];
        var dirPrior = [1, 8, 3, 4, 5, 6, 7, 2];
        AddJieToMap(jie002, initCoord, dirPrior);

        var initCoord = [0, 0];
        var dirPrior = [3, 8, 2, 4, 5, 6, 7, 1];
        AddJieToMap(jie003, initCoord, dirPrior);
        
        var initCoord = [2, 2];
        var dirPrior = [1, 8, 3, 4, 5, 6, 7, 2];
        AddJieToMap(jie004, initCoord, dirPrior);

        var initCoord = [5, 5];
        var dirPrior = [1, 8, 2, 4, 5, 6, 7, 3];
        AddJieToMap(jie005, initCoord, dirPrior);
        
        document.getElementById("fstRow").innerHTML = "output"; 
    </script>
</body>
</html>

